﻿using Antlr4.Runtime;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Text;
using ttparser;

namespace test.vistor
{
    [TestClass]
    public class UnitTest_math4
    {
        [TestMethod]
        public void calc()
        {
            var parser = dumptool.GetParserInfo<ttparser.math4Lexer, ttparser.math4Parser>("root");

            var ast = parser.Parse("1+(2+2)*3+3", true, false, false);

            valueof v = new valueof();
            var mytree = v.Visit(ast);
            Assert.AreEqual(mytree, 16, "这个表达式的值应该=16");
        }
        //visit 模式 可以把通用的ast 变成 我们的类型化的
        class valueof : ttparser.math4BaseVisitor<double>
        {

            public override double VisitRoot([NotNull] math4Parser.RootContext context)
            {                
                //直接下探
                return base.Visit(context.GetChild(0));

                //直接用默认实现也可以
                //var r = base.VisitRoot(context);
                //return r;
            }
            public override double VisitExpr([NotNull] math4Parser.ExprContext context)
            {
                //直接下探
                return base.Visit(context.GetChild(0));
            }
            public override double VisitTerminal([NotNull] ITerminalNode node)
            {
                var lexer = node.Symbol.TokenSource as Lexer;
                var type = lexer.Vocabulary.GetSymbolicName(node.Symbol.Type);
                var text = node.GetText();
                if (type == "INT")
                    return int.Parse(text);
                else if (type == "FLOAT")
                    return double.Parse(text);
                throw new Exception("unkown value:" + type + "=" + text);
            }
            public override double VisitErrorNode([NotNull] IErrorNode node)
            {
                return base.VisitErrorNode(node);
            }
            public override double VisitExpr_group([NotNull] math4Parser.Expr_groupContext context)
            {
                //group直接脱壳
                return base.Visit(context.GetChild(1));
            }
            public override double VisitExpr_add([NotNull] math4Parser.Expr_addContext context)
            {
                var op = context.GetChild(1).GetText();
                var left = Visit(context.GetChild(0));
                var right = Visit(context.GetChild(2));
                if (op == "+")
                    return left + right;
                else if (op == "-")
                    return left - right;

                throw new Exception("unknown op:" + op);
                //return base.VisitExpr_add(context);
            }
            public override double VisitExpr_mul([NotNull] math4Parser.Expr_mulContext context)
            {
                var op = context.GetChild(1).GetText();
                var left = Visit(context.GetChild(0));
                var right = Visit(context.GetChild(2));
                if (op == "*")
                    return left * right;
                else if (op == "/")
                    return left / right;

                throw new Exception("unknown op:" + op);
            }
        }
        
    }
}
